package com.example.ziputil.utils;

import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.Charset;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

@Slf4j
public class ZipUtil {

    /**
     *
     * @param zipfilePath
     * @param unZipPath
     * @throws IOException
     */
    public static void unZipKKK(String zipfilePath, String unZipPath) throws IOException {
        File file = new File(unZipPath);
        if (!file.exists()){
            file.mkdir();
        }
        //读压缩文件
        ZipInputStream zis = new ZipInputStream(new FileInputStream(zipfilePath), Charset.forName("GBK"));
        ZipEntry zipEntry;
        while ((zipEntry = zis.getNextEntry()) != null){
            if (!zipEntry.isDirectory()){
                FileOutputStream fos = new FileOutputStream(unZipPath + zipEntry.getName().split("/")[1]);
                BufferedOutputStream bos = new BufferedOutputStream(fos);
                int len;
                byte[] bufs = new byte[1024];
                while ((len = zis.read(bufs)) != -1){
                    bos.write(bufs, 0, len);
                }
                bos.close();
                fos.close();
            }else {

            }
        }
        zis.close();
    }

    /**
     * 压缩文件
     * @param sourceFileName
     * @param response
     */
    public static void zip(String sourceFileName, HttpServletResponse response){
        ZipOutputStream out = null;
        BufferedOutputStream bos = null;
        try {
            //将zip以流的形式输出到前台
            response.setHeader("content-type", "application/octet-stream");
            response.setCharacterEncoding("utf-8");
            // 设置浏览器响应头对应的Content-disposition
            //参数中 testZip 为压缩包文件名，尾部的.zip 为文件后缀
            response.setHeader("Content-disposition",
                    "attachment;filename=" + new String("压缩包".getBytes("gbk"), "iso8859-1")+".zip");
            //创建zip输出流
            out = new ZipOutputStream(response.getOutputStream());
            //创建缓冲输出流
            bos = new BufferedOutputStream(out);
            File sourceFile = new File(sourceFileName);
            //调用压缩函数
            compress(out, bos, sourceFile, sourceFile.getName());
            out.flush();

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            IOCloseUtil.close(bos, out);
        }
    }

    /**
     * 递归压缩指定文件目录
     * @param out
     * @param bos
     * @param sourceFile
     * @param base
     */
    public static void compress(ZipOutputStream out, BufferedOutputStream bos, File sourceFile, String base){
        FileInputStream fos = null;
        BufferedInputStream bis = null;
        try {
            //如果路径为目录（文件夹）
            if (sourceFile.isDirectory()) {
                //取出文件夹中的文件（或子文件夹）
                File[] flist = sourceFile.listFiles();
                if (flist.length == 0) {//如果文件夹为空，则只需在目的地zip文件中写入一个目录进入点
                    out.putNextEntry(new ZipEntry(base + "/"));
                } else {//如果文件夹不为空，则递归调用compress，文件夹中的每一个文件（或文件夹）进行压缩
                    for (int i = 0; i < flist.length; i++) {
                        compress(out, bos, flist[i], base + "/" + flist[i].getName());
                    }
                }
            } else {//如果不是目录（文件夹），即为文件，则先写入目录进入点，之后将文件写入zip文件中
                out.putNextEntry(new ZipEntry(base));
                fos = new FileInputStream(sourceFile);
                bis = new BufferedInputStream(fos);

                int tag;
                //将源文件写入到zip文件中
                while ((tag = bis.read()) != -1) {
                    out.write(tag);
                }
                bis.close();
                fos.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            IOCloseUtil.close(bis,fos);
        }
    }


}
